#ifndef USER_H
#define USER_H

#include <time.h>

#include <string>
#include <vector>
#include <algorithm>

class PasswordIncorrect:public std::exception{
	public:
		PasswordIncorrect()throw(){}
		~PasswordIncorrect()throw(){}
		const char* what()throw(){
			return "Password incorrect";
		}
	private:
		std::string s;
};
class BuddyAlreadyExists:public std::exception{
	public:
		BuddyAlreadyExists(const std::string& s)throw():buddyemail(s){}
		~BuddyAlreadyExists()throw(){}
		const char* what()throw(){
			return ("Buddy already exists:"+buddyemail).c_str();
		}
	private:
		std::string buddyemail;
};
class BuddyEmailInvalid:public std::exception{
	public:
		BuddyEmailInvalid(const std::string& s)throw():buddyemail(s){}
		~BuddyEmailInvalid()throw(){}
		const char* what()throw(){
			return ("Buddy email invalid:"+buddyemail).c_str();
		}
	private:
		std::string buddyemail;
};
class User{
	public:
		User(const std::string& email,
			const std::string& username,
			const std::string& password_hash,
			const std::vector<std::string>& buddies):
			email(email), username(username), password_hash(password_hash), buddies(buddies), online(false){}
				
		~User(){}
		std::string getEmail()const{
			return email;
		}
		std::string getUsername()const{
			return email;
		}
		std::string getPasswordHash()const{
			return email;
		}
		const std::vector<std::string>& getBuddies()const{
			return buddies;
		}
		void setUsername(const std::string& username){
			this->username=username;
		}
		void setPasswordHash(const std::string& password_hash){
			this->password_hash=password_hash;
		}
		void addBuddy(const std::string& buddyemail){
			//do not allow addition of empty buddy
			if(buddyemail=="")throw BuddyEmailInvalid(buddyemail);
			
			//do not allow for same buddy to be added twice
			if(std::find(buddies.begin(),buddies.end(),buddyemail)==buddies.end()){
				buddies.push_back(buddyemail);
			}
			else{
				throw BuddyAlreadyExists(buddyemail);
			}
		}
		void removeBuddy(const std::string& buddyemail){
			g_debug("User::removeBuddy()");
			std::vector<std::string>::iterator itr=buddies.begin();
			while(itr!=buddies.end()){
				if(*itr==buddyemail){
					g_debug("found buddy");
					itr=buddies.erase(itr);
					g_debug("erased buddy");
				}
				else{
					itr++;
				}
			}
			g_debug("done removing buddy");
		}
		void login(const std::string& password_hash){
			if(password_hash==this->password_hash){
				online=true;
				last_sync=time(0);
			}
			else {
				throw PasswordIncorrect();
			}
		}
		void logout(){
			online=false;
		}
		bool isOnline()const{
			static time_t timeout=10;
			
			if(!online){
				return false;
			}
			
			time_t now=time(0);
			bool timed_out=now-last_sync>timeout;
			if(timed_out){
				g_debug("%s has timed out", email.c_str());
				online=false;
				return false;
			}
			else{
				g_debug("%s: elapsed:%d", email.c_str(), (int)(now-last_sync));
				return true;
			}
		}
		void syncTime(){
			last_sync=time(0);
			g_debug("%s synched",  email.c_str());
		}
	private:
		std::string email;
		std::string username;
		std::string password_hash;
		std::vector<std::string> buddies;
		time_t last_sync;
		mutable bool online;
};
#endif
